﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Windows.Forms;
using BillsPresentation;
using BillsDomain;

[assembly: CLSCompliant(true)]
namespace Bills
{
    /// <summary>
    /// Interaction logic for FormPaymentReminder
    /// </summary>
    public partial class FormPaymentReminder : Form, IPaymentReminderView
    {
        /// <summary>
        /// Occurs when the delete button is clicked.
        /// </summary>
        public event EventHandler DeleteClicked;

        /// <summary>
        /// Occurs when the an item used to calculate the projected balance is changed.
        /// </summary>
        public event EventHandler ProjectedBalanceItemsChanged;

        /// <summary>
        /// The form for adding and editing payments
        /// </summary>
        private FormAddPayment addPaymentForm;

        /// <summary>
        /// This form's presenter
        /// </summary>
        private readonly PaymentReminderPresenter presenter;

        /// <summary>
        /// Initializes a new instance of the <see cref="FormPaymentReminder"/> class.
        /// </summary>
        public FormPaymentReminder()
        {
            InitializeComponent();
            this.presenter = new PaymentReminderPresenter(this, new ScheduledPaymentController());
        }

        /// <summary>
        /// Handles the Click event of the buttonAddPayment control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void buttonAddPayment_Click(object sender, EventArgs e)
        {
            if (addPaymentForm == null)
                addPaymentForm = new FormAddPayment(this.presenter.Controller);

            addPaymentForm.AddMode = true;
            addPaymentForm.ShowDialog(this);
        }

        /// <summary>
        /// Gets or sets the list of upcoming payments.
        /// </summary>
        /// <value>The upcoming payments.</value>
        public UpcomingPaymentsCollection UpcomingPayments
        {
            get { return this.bindingSourcePaymentsWithDates.DataSource as UpcomingPaymentsCollection; }
            set
            {
                this.bindingSourcePaymentsWithDates.DataSource = value;
                //this.dataGridViewUpcomingPayments.DataSource = null;
                this.dataGridViewUpcomingPayments.DataSource = this.bindingSourcePaymentsWithDates;
            }
        }

        /// <summary>
        /// Gets or sets the first date to consider when generating the upcoming payment list and the projected balance.
        /// </summary>
        /// <value>As of day.</value>
        public DateTime AsOfDay
        {
            get { return this.dateTimePickerAsOfDay.Value; }
            set { this.dateTimePickerAsOfDay.Value = value; }
        }

        /// <summary>
        /// Gets or sets the list of days and their balances.
        /// </summary>
        /// <value>The days and balances.</value>
        public BindingList<CalendarDay> DaysAndBalances
        {
            get { return this.bindingSourceCalendarDays.DataSource as BindingList<CalendarDay>; }
            set
            {
                this.bindingSourceCalendarDays.DataSource = value;
                this.chartBalance.DataBind();
            }
        }

        /// <summary>
        /// Handles the ValueChanged event of the dateTimePickerAsOfDay control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void dateTimePickerAsOfDay_ValueChanged(object sender, EventArgs e)
        {
            if (this.AsOfDateChanged != null)
            {
                this.AsOfDateChanged(sender, e);
            }
        }

        /// <summary>
        /// Occurs when the as of date is changed.
        /// </summary>
        public event EventHandler AsOfDateChanged;

        /// <summary>
        /// Occurs when a scheduled payment is changed or added.
        /// </summary>
        public event EventHandler<ScheduledPaymentChangedEventArgs> ScheduledPaymentChanged;

        /// <summary>
        /// Occurs when the window is closed.
        /// </summary>
        public event EventHandler FormClose;

        /// <summary>
        /// Handles the FormClosing event of the FormPaymentReminder control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.Forms.FormClosingEventArgs"/> instance containing the event data.</param>
        private void FormPaymentReminder_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (this.FormClose != null)
            {
                this.FormClose(sender, EventArgs.Empty);
            }
        }

        /// <summary>
        /// Handles the Click event of the buttonEditPayment control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void buttonEditPayment_Click(object sender, EventArgs e)
        {
            //TODO: Make selected item a view property
            PaymentWithDate selectedRow = this.dataGridViewUpcomingPayments.SelectedRows[0].DataBoundItem as PaymentWithDate;
            //BillsDataSet.UpcomingPaymentRow selectedUpcomingPaymentRow = selectedRow.Row as BillsDataSet.UpcomingPaymentRow;
            if (this.ScheduledPaymentChanged != null)
            {
                this.ScheduledPaymentChanged(sender, new ScheduledPaymentChangedEventArgs() { SelectedPayment = selectedRow });
            }

            if (addPaymentForm == null)
                addPaymentForm = new FormAddPayment(this.presenter.Controller);

            addPaymentForm.AddMode = false;
            addPaymentForm.ShowDialog(this);
        }

        /// <summary>
        /// Handles the DoubleClick event of the dataGridViewUpcomingPayments control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void dataGridViewUpcomingPayments_DoubleClick(object sender, EventArgs e)
        {
            //TODO: Make selected item a view property
            //TODO: Refactor this code into another method
            PaymentWithDate r = this.dataGridViewUpcomingPayments.SelectedRows[0].DataBoundItem as PaymentWithDate;
            if (this.ScheduledPaymentChanged != null)
            {
                this.ScheduledPaymentChanged(sender, new ScheduledPaymentChangedEventArgs() { SelectedPayment = r });
            }

            if (addPaymentForm == null)
                addPaymentForm = new FormAddPayment(this.presenter.Controller);

            addPaymentForm.AddMode = false;
            addPaymentForm.ShowDialog(this);
        }

        /// <summary>
        /// Handles the Click event of the buttonDeletePayment control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void buttonDeletePayment_Click(object sender, EventArgs e)
        {
            PaymentWithDate r = this.dataGridViewUpcomingPayments.SelectedRows[0].DataBoundItem as PaymentWithDate;
            if (this.ScheduledPaymentChanged != null)
            {
                this.ScheduledPaymentChanged(sender, new ScheduledPaymentChangedEventArgs() { SelectedPayment = r });
            }

            if (this.DeleteClicked != null)
            {
                this.DeleteClicked(sender, e);
            }
        }

        /// <summary>
        /// Handles the TextChanged event of the textBoxCurrentBalance control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void textBoxCurrentBalance_TextChanged(object sender, EventArgs e)
        {
            if (this.ProjectedBalanceItemsChanged != null)
            {
                this.ProjectedBalanceItemsChanged(sender, e);
            }
        }

        /// <summary>
        /// Handles the ValueChanged event of the dateTimePickerProjectDate control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void dateTimePickerProjectDate_ValueChanged(object sender, EventArgs e)
        {
            if (this.ProjectedBalanceItemsChanged != null)
            {
                this.ProjectedBalanceItemsChanged(sender, e);
            }
        }

        /// <summary>
        /// Gets the current balance.
        /// </summary>
        /// <value>The current balance.</value>
        public decimal? CurrentBalance
        {
            get
            {
                decimal? result;
                decimal nonNullResult;
                if (!decimal.TryParse(this.textBoxCurrentBalance.Text, out nonNullResult))
                {
                    result = null;
                }
                else
                {
                    result = nonNullResult;
                }

                return result;
            }
        }

        /// <summary>
        /// Gets or sets the projected balance.
        /// </summary>
        /// <value>The projected balance.</value>
        public string ProjectedBalance
        {
            get { return this.labelProjectedBalance.Text; }
            set { this.labelProjectedBalance.Text = value; }
        }

        /// <summary>
        /// Gets the date for balance projection.
        /// </summary>
        /// <value>The date for projection.</value>
        public DateTime DateForProjection
        {
            get { return this.dateTimePickerProjectDate.Value; }
            set { this.dateTimePickerProjectDate.Value = value; }
        }

        /// <summary>
        /// Gets or sets the list of dates with payments.
        /// </summary>
        /// <value>The dates with payments.</value>
        public BindingList<CalendarDay> DatesWithPayments
        {
            get { throw new NotImplementedException(); }
            set
            {
                if (value != null)
                {
                    List<DateTime> datesWithPayments = new List<DateTime>();
                    foreach (CalendarDay item in value)
                    {
                        datesWithPayments.Add(item.Date);
                    }

                    this.monthCalendarImportantDates.BoldedDates = datesWithPayments.ToArray();
                }
            }
        }

        /// <summary>
        /// Occurs when a specific date on the calendar of days with payments is selected.
        /// </summary>
        public event EventHandler<DateSelectedEventArgs> SpecificDateSelected;

        /// <summary>
        /// Handles the DateSelected event of the monthCalendarImportantDates control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.Forms.DateRangeEventArgs"/> instance containing the event data.</param>
        private void monthCalendarImportantDates_DateSelected(object sender, DateRangeEventArgs e)
        {
            if (this.SpecificDateSelected != null)
            {
                this.SpecificDateSelected(sender, new DateSelectedEventArgs() { SelectedDate = e.Start });
            }
        }

        /// <summary>
        /// Gets or sets the day on calendar.
        /// </summary>
        /// <value>The day on calendar.</value>
        public DateTime DayOnCalendar
        {
            get { return this.monthCalendarImportantDates.SelectionStart; }
            set { this.monthCalendarImportantDates.SelectionRange = new SelectionRange(value, value); }
        }

        /// <summary>
        /// Gets or sets the list of payments for a specific day.
        /// </summary>
        /// <value>The payments for A day.</value>
        public IList<Payment> PaymentsForADay
        {
            get { return this.bindingSourcePayments.DataSource as IList<Payment>; }
            set
            {
                this.bindingSourcePayments.DataSource = value;
                this.dataGridViewPaymentsOnADay.DataSource = null;
                this.dataGridViewPaymentsOnADay.DataSource = this.bindingSourcePayments;
            }
        }

        private void exportButton_Click(object sender, EventArgs e)
        {
            this.exportSaveFileDialog.ShowDialog();
            this.PathToData = this.exportSaveFileDialog.FileName;
            if (this.DataExporting != null)
            {
                this.DataExporting(this.DataExporting, EventArgs.Empty);
            }
        }


        public string PathToData
        {
            get;
            set;
        }

        public string DataFileName
        {
            get;
            set;
        }

        public event EventHandler DataExporting;

        public event EventHandler DataImporting;

        private void importButton_Click(object sender, EventArgs e)
        {
            this.importOpenFileDialog.ShowDialog();
            this.PathToData = this.importOpenFileDialog.FileName;
            if (this.DataImporting != null)
            {
                this.DataImporting(this.DataExporting, EventArgs.Empty);
            }
        }
    }
}
